<html>
<head><meta charset="utf-8"><title>async vision - one use case in gui app · wg-async-foundations · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/index.html">wg-async-foundations</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html">async vision - one use case in gui app</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="229181820"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229181820" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229181820">(Mar 07 2021 at 11:55)</a>:</h4>
<p>Hello, my friend and i talked about a very specific use case. I'm not sure yet whether async programming is the best solution here:  He is writing a game program, and </p>
<ol>
<li>plans to run the main window loop on main thread </li>
<li>want to spawn small tasks like updating data structure values in other threads, some of the inputs of these tasks are short-term borrows, so he has to use some scoped thread API like <code>rayon::Scoped</code>. </li>
<li>want to be notified about the result of the task in the main thread, when it's done, end the borrow and the scoped thread, and use the previously borrowed data for follow-up work.</li>
</ol>



<a name="229181918"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229181918" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229181918">(Mar 07 2021 at 11:56)</a>:</h4>
<p>Currently <code>winit</code>'s event loop api is <a href="https://docs.rs/winit/0.24.0/winit/event_loop/struct.EventLoop.html#method.run">this</a>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">run</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">event_handler</span>: <span class="nc">F</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">F</span>: <span class="o">'</span><span class="nb">static</span> <span class="o">+</span><span class="w"> </span><span class="nb">FnMut</span><span class="p">(</span><span class="n">Event</span><span class="o">&lt;'</span><span class="nb">_</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">EventLoopWindowTarget</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">ControlFlow</span><span class="p">),</span><span class="w"></span>
</code></pre></div>



<a name="229181998"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229181998" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229181998">(Mar 07 2021 at 11:58)</a>:</h4>
<p>When event_handler is a normal closure, it's quite hard to express the "scoped thread" scope using safe rust, because it's actually discontinous from a control flow perspective.</p>



<a name="229182146"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229182146" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229182146">(Mar 07 2021 at 12:00)</a>:</h4>
<p>I feel async programming and the interior generator might help with this use case here. I'm a little unsure about the details.</p>



<a name="229182352"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229182352" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229182352">(Mar 07 2021 at 12:03)</a>:</h4>
<p>There're also some previous discussions at <a href="https://github.com/rust-windowing/winit/issues/1199">github</a></p>



<a name="229253338"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229253338" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Didrik Nordstrom <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229253338">(Mar 08 2021 at 06:22)</a>:</h4>
<p>It's not possible to do scoped tasks - i.e. the equivalent of scoped threads - in safe async Rust. Scoped threads use a scope (hence the name) to ensure destruction of the handle (or panic - if it comes to that). I wrote a <a href="https://internals.rust-lang.org/t/pre-rfc-leave-auto-trait-for-reliable-destruction/13825">pre-RFC</a> for this (although I was not the first - there's a lot of history) since this is a super legit and likely common use-case.</p>



<a name="229254324"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229254324" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Didrik Nordstrom <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229254324">(Mar 08 2021 at 06:37)</a>:</h4>
<p>How small is this "small task"? Can this task be made synchronous or does it need to suspend?</p>
<p>In async Rust, there are combinators (the join and select macros) that are low overhead and allow static borrowing. However, they multiplex work within the same task. Joining is technically done on two <em>futures</em>, but logically speaking these can as well be considered <em>tasks</em>. It's preferable to spawning a "Real Task", typically.</p>
<p>If <em>different</em> tasks need to cooperate, you typically use a shared <code>Arc&lt;Mutex&lt;T&gt;&gt;</code> or a message passing channel between the different tasks.</p>



<a name="229350300"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229350300" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Charles Lew <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229350300">(Mar 08 2021 at 18:33)</a>:</h4>
<p>Thanks for the explanation! It seems i need to think more about this and maybe i'll need to implement the needed synchroization manually.</p>



<a name="229374400"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/187312-wg-async-foundations/topic/async%20vision%20-%20one%20use%20case%20in%20gui%20app/near/229374400" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Didrik Nordstrom <a href="https://rust-lang.github.io/zulip_archive/stream/187312-wg-async-foundations/topic/async.20vision.20-.20one.20use.20case.20in.20gui.20app.html#229374400">(Mar 08 2021 at 21:11)</a>:</h4>
<p>Sure! The current async ecosystem is tailored for servers - so most work has gone into optimizing for the <em>multithreaded, work-stealing</em> type of executors/runtimes, where the workload is assumed to be uniform in terms of scheduling requirements. Most do <em>not</em> offer thread affinity, task priorities, deadlines which you might want if you're writing games, device drivers etc - e.g. workloads where you have a latency-sensitive UI thread/task loop.</p>
<p>There is nothing prevent async Rust focusing on that - in fact, the <a href="https://github.com/bastion-rs/bastion">Bastion</a> runtime has been innovating in this space, but still with focus on servers. I suspect that if you want most bang-for-the-buck building a game <em>today</em>, your best bet is a good thread pool library and synchronous concurrent data structures (e.g. <a href="https://github.com/crossbeam-rs/crossbeam">crossbeam</a> and/or <a href="https://github.com/Amanieu/parking_lot">parking_lot</a>).</p>
<p>That said, if you are ok with digging deeper, you might consider:</p>
<ul>
<li>Run a hybrid system I/O workloads run on some threads. Challenges would be finding interoperable concurrent data structures and debugging/profiling might be more difficult.</li>
<li>Write or extend an async Runtime to support deadlines/priorities/&lt;other custom behavior&gt; and use async throughout. This is inherently complex and might require rewriting code for async (both your own code and crates you're currently using)</li>
</ul>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>